#ifndef JLOG_H
#define JLOG_H

#include <QObject>
#include <QString>
#include <QList>

//! log entry type classifications
const enum JLogEntryType
{
	JLOG_INFO = 0,
	JLOG_SUCCESS,
	JLOG_WARNING,
	JLOG_ERROR,
	JLOG_CRITICAL,
};

//! describes a log entry struct
struct JLogEntry
{
	unsigned short mType;	//! JLogEntryType type
	QString mTime;			//! time stamp
	QString mMsg;			//! message string
	bool bSubEntry;			//! is a sub log entry
};

//! static log class that contains logging related operations
class JLog : public QObject
{
	Q_OBJECT

public:
	static JLog& Instance(void);

	//! brief\ use to log a message
	/*!
		There are two log message types. One classified as a top level message and the other 
		as a sub level message. A top level message is posted by passing a string message without
		specifying the associated message type. The top level message is logged directly into the
		log file upon posting. A top level message is the default way of logging a simple message.
		A sub level message is posted in a similar way with the additional message type parameter
		specified. Posting of sub level message(s) must be followed by a top level message serving
		as the header message for the sub message(s) group. Unlike the top level messages, sub
		level messages are not logged to a file until after a top level message closes the group.
		This way, sub level message posting does not eat extra processor time opening and closing
		and can be used in processor intensive algorithms. An example follows:

		intensive for loop {
		JLOG::PostSub("sub level message", JLOG_SUCCESS);
		}
		JLOG::Post("top level message");

		output:
		- top level message
			sub level message
			sub level message
			...
		
		Note: numerical values can be added into log messages by first casting them into QString 
		by using Qt's QString library function: QString::number(value)
	*/

public slots:
	//! use to log a top level message, default type
	void Post(const QString &, unsigned short msgType = JLOG_INFO);
	//! use to log a sub level message
	void PostSub(const QString &, unsigned short msgType = JLOG_INFO);

	//! use when a GUI widget is unavailable to display output
	void LogToFile(const QString &, unsigned short msgType = JLOG_INFO);

	//! use to clear/create a log file, call this method first-thing in the main() with log file name
	void ClearLog(const QString &);

signals:
	//! send the log entry struct to the associated log widget
	void sendPost(JLogEntry *mLogEntry);
	void sendList(QList<JLogEntry> *);

private:
	JLog(void);
	JLog(const JLog &);
	~JLog(void);

	//! gets current time with default tick resolution of 1000. For example, 02:23:43.782
	QString getTimeTick(int tickResolution = 1000);
	//! converts the message type to corresponding string for log file output
	QString msgTypeToString(unsigned short msgType);
	//! write the message to file
	void writeToFile(const QString &mMsg);

	QString		m_CurrentLogFileName;
	JLogEntry	m_LastEntry;
	unsigned short	 m_HighestError;
	QList<JLogEntry> m_LogEntryList;
};

//! for convenience JLOG::Post(...) can be used as a shorthand alternative to JLog::Instance().Post(...)
#define Log JLog::Instance()

#endif // JLOG_H
